package com.hyxt.DTO;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.hyxt.DTO.protocols.*;
import com.hyxt.dao.RedisServiceDAO;
import com.hyxt.utils.bytes.BytesUtil;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import java.net.InetSocketAddress;
import java.util.HashMap;
import java.util.Map;

import static com.hyxt.DTO.TermianaUtil.findIpAndPort;

/**
 * @Description: Server接收消息处理类
 * @author shenp
 */
public class ServerHandler extends ChannelInboundHandlerAdapter {
    /**
     * 链路对象缓存
     */
    public final static Map<String,Channel> channleMap = new HashMap<String,Channel>();
    /**
     * 唯一标识与链路对应关系缓存
     */
    public final static Map<String,String> signMap = new HashMap<String,String>();
    /**
     * 日志
     */
    private static Log log = LogFactory.getLog(ServerHandler.class
            .getName());
    /**
     * @Description 数据处理类
     */
    private DataHandler handle;
    /**
     * @Description协议类型
     */
    private String protocol = "";
    /**
     * 终端ip
     */
    private String ip;
    /**
     * 终端端口
     */
    private Integer port;
    /**
     * 唯一标识
     */
    private String sign = "";
    /**
     * 输入数据缓存
     */
    private ByteBuf in = Unpooled.buffer();
    /**
     * 输出数据缓存
     */
    private ByteBuf out =  Unpooled.buffer();
    /**
     * 协议对象
     */
    private ICase iCase;
    /**
     * redis对象
     */
    @Reference(version = "1.0.0")
    RedisServiceDAO redisServiceDAO;


    public ServerHandler(){}

    public ServerHandler(DataHandler handle,RedisServiceDAO redisServiceDAO){
        this.handle = handle;
        this.redisServiceDAO = redisServiceDAO;
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        //当前时间戳
        long time = System.currentTimeMillis();
         //原始数据
        byte[] byteMessage = (byte[]) msg;
        log.info(BytesUtil.bytesToHexString(byteMessage));
        //第一条数据
        if ("".equals(protocol)){
            //解析协议类型
            protocol = handle.judgeProtocol(byteMessage);
            //根据协议类型获取唯一标识
            switch (protocol){
                case "ET08" :
                    iCase = new ET08Case();
                    sign = iCase.getSign(byteMessage);
                    //唯一标识与链路对应关系缓存
                    signMap.put(sign,ip+port);
                    break;
                case "HUAQ":
                    iCase = new HUAQCase();
                    sign = iCase.getSign(byteMessage);
                    //唯一标识与链路对应关系缓存
                    signMap.put(sign,ip+port);
                    break;
                case "JM":
                    iCase = new JMCase();
                    sign = iCase.getSign(byteMessage);
                    //唯一标识与链路对应关系缓存
                    signMap.put(sign,ip+port);
                    break;
                case "OY":
                    iCase = new OYCase();
                    sign  = iCase.getSign(byteMessage);
                    //唯一标识与链路对应关系缓存
                    signMap.put(sign,ip+port);
                    break;
                case "T808":
                    iCase = new T808Case();
                    sign = iCase.getSign(byteMessage);
                    //唯一标识与链路对应关系缓存
                    signMap.put(sign,ip+port);
                    break;
                case "TIANQ":
                    iCase = new TIANQCase();
                    sign = iCase.getSign(byteMessage);
                    //唯一标识与链路对应关系缓存
                    signMap.put(sign,ip+"-"+port);
                    break;
                default:
            }
        }else {
           //完整包校验
            in.writeBytes(byteMessage);
            byteMessage = iCase.disassemblyByByteBuf(in);
            if (byteMessage==null){
                return;
            }
        }
        //发送数据到监听通道
        JSONObject sendMsg =new JSONObject();
        sendMsg.put("protocol",protocol);
        sendMsg.put("sign",sign);
        sendMsg.put("time",time);
        sendMsg.put("datas",new String(byteMessage));
        redisServiceDAO.sendMessage("termianalMessage", JSON.toJSONString(sendMsg));
    }

    /**
     * 链路建立
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        InetSocketAddress ipPort = (InetSocketAddress) ctx.channel().remoteAddress();
        //获取客户端ip
        ip = ipPort.getAddress().toString().substring(1);
        //获取客户端端口
        port = ipPort.getPort();
        //将链路存入到内存中
        channleMap.put(ip+"-"+port,ctx.channel());
    }

    /**
     * 链路断开
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        String ipAndPort = findIpAndPort(sign);
        signMap.remove(sign);
        if (!"".equals(ipAndPort)){
            channleMap.remove(ipAndPort);
        }
    }

    /**
     * 链路异常
     * @param ctx
     * @param cause
     * @throws Exception
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        String ipAndPort = findIpAndPort(sign);
        if (!"".equals(ipAndPort)){
            signMap.remove(sign);
            channleMap.remove(ipAndPort);
        }
    }
}
